package com.javasm.boot.oauth2.utils;

import com.javasm.boot.oauth2.entity.MyAuthentication;
import com.javasm.boot.oauth2.entity.Perm;
import io.jsonwebtoken.lang.Assert;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;

import javax.annotation.PostConstruct;
import java.util.*;
import java.util.stream.Collectors;

/**
 * Author：MoDebing
 * Version：1.0
 * Date：2022-12-13-12:18
 * Description:
 */
@Component
@Slf4j
@AllArgsConstructor
@Data
public class IgoreUrlByRedis {


    private WebApplicationContext applicationContext;

    //白名单
    private List<String> ignoreUrls;

    // 黑名单
    private List<String> urls;


    // 获取白名单和非白名单路径
    @PostConstruct
    public void init(){
        RequestMappingHandlerMapping mapping = applicationContext.getBean(RequestMappingHandlerMapping.class);
        List<String> ignoreUrls = new ArrayList<>();
        List<String> authenticationUrls = new ArrayList<>();
        //获取url与类和方法的对应信息
        Map<RequestMappingInfo, HandlerMethod> map = mapping.getHandlerMethods();
        Map<String, List<String>> permissionUrlMap = new HashMap<>();


        // 获取url的Set集合，一个方法可能对应多个url
        for (Map.Entry<RequestMappingInfo, HandlerMethod> entry : map.entrySet()) {
            //一个方法可能有多个url指向它
            Assert.notNull(entry.getKey().getPatternsCondition());
            Set<String> urls = entry.getKey().getPatternsCondition().getPatterns();
            // 获取权限
            Perm perm = entry.getValue().getMethodAnnotation(Perm.class);
            List<String> permissions = new ArrayList<>();
            if (Objects.nonNull(perm)){
                MyAuthentication[] authentications = perm.value();
                List<String> list = Arrays.stream(authentications).map(MyAuthentication::getPermission).collect(Collectors.toList());
                permissions.addAll(list);
            }

            //将路径和权限都存入到redis当中
            urls.stream().distinct().forEach(url->{
                // 把所有的黑名单和白名单放到redis当中。黑名单和白名单用权限注解Perm区分
                permissionUrlMap.put(url,permissions);
                if (permissions.size() == 0){
                    ignoreUrls.add(url);
                }else {
                    authenticationUrls.add(url);
                }
            });
        }
        ignoreUrls.add("/oauth/token");
        ignoreUrls.add("/oauth/token_key");
        ignoreUrls.add("/oauth/check_token");
        this.ignoreUrls = ignoreUrls.stream().distinct().collect(Collectors.toList());
        this.urls = authenticationUrls.stream().distinct().collect(Collectors.toList());
        log.info(this.ignoreUrls.toString());
        log.info(this.urls.toString());
    }
}
